/* file: cg_node.h */

#ifndef _CG_NODE_H
#define _CG_NODE_H

#include "gp.h"
#include "cg_image.h"
#include "correspond.h"
#include "dispatcher.h"


/*************************************************
class name: CGNode
*************************************************/
class CGNode
{
protected:
    /* config information */
    string ip;
    int level;
    CGNodeStatus status;
    
    /* image of CGNode */
    CGImage image;

    /* resource dispatcher */
    Dispatcher dispa;

protected:
    /* heart beat variables */
    unsigned int hb_sec;	// seconds of sending heartbeat
    unsigned int hb_timeout;	// seconds of timeout
    unsigned int count_sec; 
    map<string, int> hb_table;	// check the heart_beat of its children
    
    //map<string, int> reg_table;
    //int count;

    int depth;
    char seg_ip[30];
    int file_listenfd;
    //int count;
    map<string, int> rs_children;	// check the action of getting resource_list from child;
    int childnum;
    Set children;

    map<string, vector<Position>::iterator> childptr;	// uesd in resource dispatching
    

public:
    CGNode();
    CGNode(string node_ip, int node_level);
    
public:
    void initCGNode(string node_ip, int node_level, string root, int sub_depth, char *str);
    string getIP() { return this->ip; }
    int getLevel() { return this->level; }
    int getDepth() { return image.getDepth(); }
    string getFather() { return image.getFather(); }
    void getFather(char *father) { strcpy(father, (image.getFather()).c_str()); }

    int loadSubImage(char *str);

    int indexChldNode(string cur_ip, int cur_level, Set *set);

    void codeCGImage(char *str) { image.codeCGImage(this->ip, this->level, str); }
    
public:		/* param of heart_beat */
    CGNodeStatus getStatus() { return this->status; }
    void setStatus(CGNodeStatus stat) { status = stat; }
    unsigned int getHBsec() { return hb_sec; }
    unsigned int getHBtimeout() { return hb_timeout; }
    void setHBsec(unsigned int sec) { hb_sec = sec; }
    void setHBtimeout(unsigned int sec) { hb_timeout = sec; }
    
public:
    void registerCGNode();
    int recvMessage(MessageType t, string sender, int s_level, char *str);
    int recvHeartBeat(MessageType t, string child, char *str);
    int sendHeartBeat(int load);
    
    int checkTimeout();
    int do_ack(string sender, int s_level);
    int do_adjust(Set set, CGNodeStatus stat);
    int do_update(string child, int s_level, char *str);
    int do_reconstruct(char *str);
    int do_reconfig(string father);
    int do_add(string sender, char *str);
    int do_del(char *str);

    int match_ip(char *ip);
    int findFit(char *filename, char *ip);
    int has_source(char *filename);

    int fileToMap(char *filename) { return dispa.fileToMap(filename); }
    int mapToFile(char *filename) { return dispa.mapToFile(filename, this->level); }
    void strToMap(char *str) { return dispa.strToMap(str); }
    void mapToStr(char *str) { return dispa.mapToStr(str); }

    int sendFile(const char* ip,char* filename);
    int listenFile();
    int recvFile(char *filename, string sender);
    int receiveFile(int listenfd,char* file);

    int addRSList(string child);
    int removeRSList(string child);
    int updateRSList(string child);
    int reconstructRSList();
    
    void setListenfd(int listenfd){file_listenfd = listenfd;}
    int getFile_listenfd(){return file_listenfd;}

    //void setCount(){count = 0;}
    //int getCount(){return count;}
    int getChildNum(){return childnum;}
    int setChildNum(int num){childnum = num;}
    //int addCount(){count++;}

    /* used in resource dispatching */
    int sendFirstChild(char* str);
    int sendNextChild(char* str);
    void sendSuccess(char* str);
    void sendFail(char* str);
    void erase(char* str);
  
    void addIndex(char* ip,char* filename){dispa.addIndex(ip,filename);}
    void deleteIndex(char* ip,char* filename){dispa.deleteIndex(ip,filename);}
    void setLoad(int load) { dispa.setLoad(this->ip, load); }
};

#endif
